/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月28日
 */
package com.massyframework.beanskin.launcher;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.massyframework.beanskin.ModuleIdentifier;
import com.massyframework.beanskin.ModuleJarsLocator;
import com.massyframework.beanskin.SimpleModuleIdentifier;
import com.massyframework.beanskin.framework.Framework;
import com.massyframework.beanskin.framework.FrameworkConfig;
import com.massyframework.beanskin.launcher.deploying.FrameworkDeployer;
import com.massyframework.beanskin.launching.LaunchingHandler;
import com.massyframework.beanskin.util.localstore.LocalStore;

/**
 * 运行框架配置处理器
 * @author huangkh
 *
 */
class FrameworkConfigProcessing {

	private Logger logger = LoggerFactory.getLogger(FrameworkConfigProcessing.class);
	
	/**
	 * 
	 */
	public FrameworkConfigProcessing() {
	}

	/**
	 * 查找FrameworkConfig
	 * @param localStore {@link LocalStore}
	 * @return {@link FrameworkConfig}
	 */
	protected FrameworkConfig lookupFrameworkConfig(Map<String, String> configuration, LocalStore localStore) {
		String text = configuration.getOrDefault(Framework.DEBUG_MODEL, "false");
		boolean debug = Boolean.parseBoolean(text);
		
		FrameworkDeployer deployer = new FrameworkDeployer(localStore);
		
		Set<ModuleIdentifier> deployModules = new HashSet<>();
		ModuleJarsLocator locator = deployer.deployAndLocate(debug, deployModules);
		
		ClassLoader classLoader = this.createFrameworkClassLoader(locator);
		FrameworkConfig result = this.loadService(FrameworkConfig.class, classLoader);
		
		if (result != null) {
			for (Map.Entry<String, String> entry: configuration.entrySet()) {
				result.setParameter(entry.getKey(), entry.getValue());
			}
			
			result.defineExportService(LocalStore.class.getName(), localStore, 
					builder->{
						builder.addExportService(LocalStore.class)
							.description("提供本地存储服务，支持将数据或者文件存储在本地文件系统上。");
					});
			result.addBean(ModuleJarsLocator.class.getName(), locator);	
			result.setAttribute(ClassLoader.class.getName(), classLoader);
			result.setAttribute(FrameworkConfig.DEPLOY_MODULES, deployModules);
		}
			
		return result;
	}
	
	/**
	 * 初始化处理
	 * @param handlers {@link List},处理器集合
	 * @param config {@link FrameworkConfig},运行框架配置器
	 */
	protected void initialize(List<LaunchingHandler> handlers, FrameworkConfig config) {
		if (handlers == null) return;
		
		for (LaunchingHandler handler: handlers) {
			try {
				handler.init(config);
			}catch(Exception e) {
				if (logger.isErrorEnabled()) {
					logger.error(e.getMessage(), e);
				}
			}
		}
	}
			
	/**
	 * 创建Framework的类加载器
	 * @param locator {@link ModuleJarsLocator}
	 * @return {@link ClassLoader}
	 */
	protected ClassLoader createFrameworkClassLoader(ModuleJarsLocator locator) {
		ModuleIdentifier module = 
			SimpleModuleIdentifier.createModuleIdentifierWithKernel();
		List<URL> urls = locator.locate(module);
		
		FrameworkClassLoader result =
				FrameworkClassLoader.newBuilder()
					.moduleIdentifier(module)
					.addURLs(urls)
					.parentClassLoader(this.getClass().getClassLoader())
					.build();
		return result;
	}
	
	/**
	 * 按{@code serviceType}从{@code classLoader}通过java spi加载任意一个服务
	 * @param <T>
	 * @param serviceType {@link Class},服务类型
	 * @param classLoader {@link ClassLoader},类加载器
	 * @return {@link T}
	 */
	protected <T> T loadService(Class<T> serviceType, ClassLoader classLoader) {
		ServiceLoader<T> sl = ServiceLoader.load(serviceType, classLoader);
		Iterator<T> it = sl.iterator();
		return it.hasNext() ? it.next() : null;
	}
	
	/**
	 * 按{@code serviceType}从{@code classLoader}通过java spi加载所有服务
	 * @param <T>
	 * @param serviceType {@link Class},服务类型
	 * @param classLoader {@link ClassLoader},类加载器
	 * @return {@link T}
	 */
	protected <T> List<T> loadServices(Class<T> serviceType, ClassLoader classLoader){
		List<T> result = new ArrayList<>();
		ServiceLoader<T> sl = ServiceLoader.load(serviceType, classLoader);
		Iterator<T> it = sl.iterator();
		while (it.hasNext()) {
			try {
				result.add(it.next());
			}catch(Exception e) {
				if (logger.isErrorEnabled()) {
					logger.error(e.getMessage(), e);
				}
			}
		}
		
		return result;
	}
}
